package JarInfoReader

import (
	"archive/zip"
	"encoding/xml"
	"errors"
	"io"
	"strings"
)

func ReadJarInfoEntity(jarFilePath string) (*JarInfoEntity, error) {
	// 读取jar文件的静态信息
	jarInfo, err := readJarInfo(jarFilePath)
	if err != nil {
		return nil, err
	}

	// 提取dir和class信息
	entity := NewEntity()
	entity.ClassFileName = jarInfo["classFileName"].([]string)
	entity.DirectoryName = jarInfo["directoryName"].([]string)

	fileName := jarInfo["pom.xml"]
	if fileName == nil {
		return nil, errors.New("找不到pom.xml")
	}

	// 读取POM.XML文件信息
	xmlData, err := readPomXml(jarFilePath, fileName.(string))
	if err != nil {
		return nil, err
	}

	var project xmlProject

	// 解析pom格式的xml
	err = xml.Unmarshal([]byte(xmlData), &project)
	if err != nil {
		return nil, err
	}

	dependencies := project.Dependencies.Dependency
	if dependencies != nil {
		for _, dependency := range dependencies {
			item := &JarInfoItem{}
			item.GroupId = dependency.GroupId
			item.ArtifactId = dependency.ArtifactId
			item.Version = dependency.Version

			entity.Dependencies = append(entity.Dependencies, item)
		}
	}

	fileName = jarInfo["pom.properties"]
	if fileName == nil {
		return nil, errors.New("找不到pom.properties")
	}

	// 读取pom.properties文件信息
	bytes, err := getFileFromJar(jarFilePath, fileName.(string))
	if err != nil {
		return nil, err
	}

	lines := strings.Split(string(bytes), "\r\n")
	for _, line := range lines {
		if strings.HasPrefix(line, "version=") {
			entity.Properties.Version = line[len("version="):]
		}
		if strings.HasPrefix(line, "groupId=") {
			entity.Properties.GroupId = line[len("groupId="):]
		}
		if strings.HasPrefix(line, "artifactId=") {
			entity.Properties.ArtifactId = line[len("artifactId="):]
		}
	}

	return entity, err
}

func readPomXml(jarFilePath, fileName string) (string, error) {
	bytes, err := getFileFromJar(jarFilePath, fileName)
	if err != nil {
		return "", err
	}

	return string(bytes), nil
}

func getFileFromJar(jarFilePath, fileName string) ([]byte, error) {
	zipFile, err := zip.OpenReader(jarFilePath)
	if err != nil {
		return nil, err
	}
	defer zipFile.Close()

	var targetFile *zip.File
	for _, file := range zipFile.Reader.File {
		if file.Name == fileName {
			targetFile = file
			break
		}
	}

	if targetFile == nil {
		return nil, errors.New("file not found in zip")
	}

	rc, err := targetFile.Open()
	if err != nil {
		return nil, err
	}
	defer rc.Close()

	content, err := io.ReadAll(rc)
	if err != nil {
		return nil, err
	}

	return content, nil
}

func readJarInfo(jarFilePath string) (map[string]interface{}, error) {
	result := make(map[string]interface{})

	dirNames := make([]string, 0)
	classNames := make([]string, 0)

	// 打开zip文件
	zipFile, err := zip.OpenReader(jarFilePath)
	if err != nil {
		return nil, err
	}
	defer zipFile.Close()

	// 遍历zip文件中的所有文件
	for _, file := range zipFile.File {
		fileName := file.Name
		if file.FileInfo().IsDir() {
			// 目录名称
			dirNames = append(dirNames, fileName)
		} else {
			// class文件名称
			if strings.HasSuffix(fileName, ".class") {
				className := strings.ReplaceAll(fileName, "/", ".")
				classNames = append(classNames, className[0:len(className)-len(".class")])
			}

			if strings.HasPrefix(fileName, "META-INF/maven") && strings.HasSuffix(fileName, "pom.xml") {
				result["pom.xml"] = fileName
				continue
			}

			if strings.HasPrefix(fileName, "META-INF/maven") && strings.HasSuffix(fileName, "pom.properties") {
				result["pom.properties"] = fileName
				continue
			}
		}

	}

	result["directoryName"] = dirNames
	result["classFileName"] = classNames

	return result, nil
}
